package com.syyo.admin.interceptor;

import com.syyo.admin.config.datasource.DataSourceContextHolder;
import com.syyo.admin.config.security.config.TokenProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Auther: wangzhong
 * @Date: 2019/7/29 16:18
 * @Description:
 *
 *
 * 拦截器：用来动态设置数据源
 * 原理：
 *     有主服务器，租户服务器
 *     1.租户在租户的服务器登录，会调获取"/auth/db"接口从主服务器，拿到租户对应的数据源
 *     2.再调租户服务器的“/auth/login”登录接口，把数据源传过来，
 *     3.租户的登录接口将数据源保存到token里进行返回
 *     4.每个接口都会传带有数据源的token请求头，
 *     5.拦截器会根据从token里解析出数据源，动态设置对应的数据源，实现多租户，数据库隔离。
 *
 */

@Component
public class AuthorityInterceptor implements HandlerInterceptor {

    @Autowired
    private TokenProvider tokenProvider;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();

        if ("/auth/login".equals(uri)){
            String db = request.getHeader("db");
            // 登录接口，从请求头根据"db"拿到租户的数据源，
            DataSourceContextHolder.setDB(db);
        }else {
            // 其他接口，从token解析，拿到租户的数据源
            String token = tokenProvider.getToken(request);
            String db = tokenProvider.getDb(token);
            DataSourceContextHolder.setDB(db);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求结束后清除线程里的数据源
        DataSourceContextHolder.clearDB();
    }
}

